#ifndef __VIEW__H
#define __VIEW__H

#include <iostream>

#include "types.h"
#include "Image.h"
#include "Rect.h"
#include "Point.h"

// this class is responsible for storing the "state" of a view
class ViewState {
public:
	ViewState(F64 nCenterRow, F64 nCenterCol, F64 nCenterAngle) :
		m_nCenterRow(nCenterRow), 
		m_nCenterCol(nCenterCol), 
		m_nCenterAngle(nCenterAngle) {}
	ViewState(const ViewState *pState) { Set(pState); }
	ViewState *GetThis() { return this; }	
	const ViewState *GetThis() const { return this; }	
	void Set(const ViewState *pState) { 
		m_nCenterRow = pState->m_nCenterRow; 
		m_nCenterCol = pState->m_nCenterCol; 
		m_nCenterAngle = pState->m_nCenterAngle; 
	}
	Point<F64> GetPoint() { return Point<F64>(m_nCenterRow, m_nCenterCol); }
public:
	F64 m_nCenterRow;
	F64 m_nCenterCol;
	F64 m_nCenterAngle;
};

class View : protected ViewState
{
public:
	View(const Image *pImage, F64 nCenterRow, F64 nCenterCol, F64 nCenterAngle) : 
		ViewState(nCenterRow, nCenterCol, nCenterAngle),
		m_pImage(pImage) {}
	View(const Image *pImage, ViewState *pState) : 
		ViewState(pState),
		m_pImage(pImage) {}
	View *GetThis() { return this; }
	const View *GetThis() const { return this; }

	U32 GetPix(F64 nRow, F64 nCol) const;
	Image *ToImage() const;
	void OutputPixels(U8 *p, S32 nPostLineOffset, bool bRGBA) const;
	bool SaveAsImage(const char *pszFileName) 
	{ Image *p = ToImage(); bool b = p->Save(pszFileName); delete p; return b;}
	
	F64 GetCenterAngle() const { return m_nCenterAngle; }
	void SetCenterAngle(F64 nAngle) 
	{ 
		while(nAngle >= 360.0) nAngle -= 360.0; 
		while(nAngle < 0.0)    nAngle += 360.0; 
		m_nCenterAngle = nAngle; 
	}
	F64 GetCenterRow() const { return m_nCenterRow; }
	void SetCenterRow(F64 nRow) { m_nCenterRow = nRow; }
	F64 GetCenterCol() const { return m_nCenterCol; }
	void SetCenterCol(F64 nCol) { m_nCenterCol = nCol; }
	void GetBoundingRect(Rect<S32> *pRect) const;
	const Image *GetSourceImage() const { return m_pImage; }
	const ViewState *GetViewState() const { return ViewState::GetThis(); }
	ViewState *GetViewState() { return ViewState::GetThis(); }
	void SetViewState(const ViewState *pState) { ViewState::Set(pState); }
protected:
	void TransformPoints(F64 *nRow, F64 *nCol) const;
	void UntransformPoints(F64 *nRow, F64 *nCol) const;
private:
	const Image *m_pImage;
};
#endif
